/*
 *  tm1638.c
 *
 *  Created on: Feb 11, 2020
 *      Author: Administrator
 *		Node  :
 */

/* 包含头文件
 * ------------------------------------------------------------------*/
#include "tm1638.h"
/* 私有类型定义
 * -----------------------------------------------------------------*/

/* 私有宏定义
 * ------------------------------------------------------------------*/

/* 私有变量
 * -------------------------------------------------------------------*/

/* 扩展变量
 * -------------------------------------------------------------------*/

/* 私有函数原形
 * ----------------------------------------------------------------*/
static void TM1638_Write(u8 DATA); //写数据函数
static u8 TM1638_Read(void); //读数据函数
/* 函数体 --------------------------------------------------------------------*/

#define DATA_COMMAND 0X40
#define DISP_COMMAND 0x80
#define ADDR_COMMAND 0XC0

// TM1638模块引脚定义

//共阴数码管显示代码
u8 tab[] = { 0x3F, 0x06, 0x5B, 0x4F, 0x66, 0x6D, 0x7D, 0x07, 0x7F, 0x6F, 0x40 };
u8 tab2[] = { 0xBF, 0x86, 0xDB, 0xCF, 0xE6, 0xED, 0xFD, 0x87, 0xFF, 0xEF };
u8 num[8]; //各个数码管显示的值

u8 Read_key(void);

// TM1638初始化函数
void TM1638_Init(void)
{
    pinMode(STB, OUTPUT);
    pinMode(CLK, OUTPUT);
    pinMode(DIO, OUTPUT); //让三个脚都是输出状态

    u8 i;
    Write_COM(0x8b); //亮度 (0x88-0x8f)8级亮度可调
    Write_COM(0x40); //采用地址自动加1
    digitalWrite(STB, LOW); //
    TM1638_Write(0xc0); //设置起始地址
    for (i = 0; i < 16; i++) //传送16个字节的数据
        TM1638_Write(0x00);
    digitalWrite(STB, HIGH);
}

/**
 * 显示 weight 个位数码管
 */
void TM1638_DisWeightGeSeg(u8 seg, u8 num) { Write_DATA(seg * 2, tab[num]); }

/**
 * 显示 weight 十位数码管
 */
void TM1638_DisWeightShiSeg(u8 seg, u8 num) { Write_DATA(seg * 2, tab2[num]); }

void TM1638_Write(u8 DATA) //写数据函数
{
    u8 i;
    pinMode(DIO, OUTPUT);
    for (i = 0; i < 8; i++) {
        digitalWrite(CLK, LOW);
        if (DATA & 0X01)
            digitalWrite(DIO, HIGH);
        else
            digitalWrite(DIO, LOW);
        DATA >>= 1;
        digitalWrite(CLK, HIGH);
    }
}

u8 TM1638_Read(void) //读数据函数
{
    u8 i;
    u8 temp = 0;

    pinMode(DIO, INPUT); //设置为输入
    for (i = 0; i < 8; i++) {
        temp >>= 1;
        digitalWrite(CLK, LOW);
        if (digitalRead(DIO) == HIGH)
            temp |= 0x80;
        digitalWrite(CLK, HIGH);
    }
    return temp;
}
void Write_COM(u8 cmd) //发送命令字
{
    digitalWrite(STB, LOW);
    TM1638_Write(cmd);
    digitalWrite(STB, HIGH);
}
u8 Read_key(void)
{
    u8 c[4], i, key_value = 0;
    digitalWrite(STB, LOW);
    TM1638_Write(0x42); //读键扫数据 命令
    for (i = 0; i < 4; i++) {
        c[i] = TM1638_Read();
    }
    digitalWrite(STB, HIGH); // 4个字节数据合成一个字节
    for (i = 0; i < 4; i++) {
        key_value |= c[i] << i;
    }
    for (i = 0; i < 8; i++) {
        if ((0x01 << i) == key_value)
            break;
    }
    return i;
}
void Write_DATA(u8 add, u8 DATA) //指定地址写入数据
{
    Write_COM(0x44);
    digitalWrite(STB, LOW);
    TM1638_Write(0xc0 | add);
    TM1638_Write(DATA);
    digitalWrite(STB, HIGH);
}

void Write_allLED(u8 LED_flag) //控制全部LED函数，LED_flag表示各个LED状态
{
    u8 i;
    for (i = 0; i < 8; i++) {
        if (LED_flag & (1 << i))
            Write_DATA(2 * i + 1, 1);
        else
            Write_DATA(2 * i + 1, 0);
    }
}

void TM1638_ClsScreen()
{
    for (int i = 0; i < 8; i++)
        Write_DATA(i << 1, 0x00); //初始化寄存器
}
//清除某个SEG
void TM1638_ClsSeg(u8 seg) { Write_DATA(seg * 2, 0x00); }

void TM1638_DisNumSeg(u8 seg, u8 num) { Write_DATA(seg * 2, tab[num]); }

void TM1638_Test(void)
{
    u8 i;
    TM1638_Init(); //初始化TM1638
    TM1638_ClsScreen(); //清屏

    while (1) {
        i = Read_key(); //读按键值
        if (i < 8) {
            num[i]++;
            while (i == Read_key())
                ; //等待按键释放
            if (num[i] > 15)
                num[i] = 0;
            Write_DATA(i * 2, tab[num[i]]);
            Write_allLED(1 << i);
        }
    }

    //	while(1)
    //	{
    //		for (int i = 0; i < 4; i++)
    //		{
    //			for (int j = 0; j < 10; j++)
    //			{
    //				Write_DATA(i * 2, tab[j]);
    //			}
    //			delay_ms(1000);
    //		}
    //	}
}
